from rest_framework import status
from rest_framework.response import Response
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken, TokenError
from django.contrib.auth import authenticate, get_user_model

from Notebook import settings
from .serializers import (
    UserSerializer,
    VerificationCodeSerializer,
    PasswordChangeSerializer,
    UserRegistrationSerializer,
    UserLoginSerializer
)
from rest_framework.permissions import AllowAny, IsAuthenticated
from .sms import SMSClient
from django.core.cache import cache
import os
from apps.core.services.verification_service import VerificationService
import logging
from asgiref.sync import sync_to_async

# 获取自定义用户模型
User = get_user_model()

logger = logging.getLogger(__name__)


class VerifyCodeView(APIView):
    """验证码验证视图"""
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = VerificationCodeSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        phone = serializer.validated_data['phone']
        code = serializer.validated_data['verification_code']

        cache_key = f"verification_code_{phone}"
        cached_code = cache.get(cache_key)

        if not cached_code or cached_code != code:
            return Response(
                {'verification_code': '验证码错误或已过期'},
                status=status.HTTP_400_BAD_REQUEST
            )

        return Response({
            'message': '验证码验证成功',
            'phone': phone
        }, status=status.HTTP_200_OK)


class BaseResponse:
    @staticmethod
    def success(data=None, message="操作成功"):
        return Response({
            "status": "success",
            "message": message,
            "data": data
        })

    @staticmethod
    def error(message="操作失败", status=status.HTTP_400_BAD_REQUEST):
        return Response({
            "status": "error",
            "message": message
        }, status=status)


class RegisterView(APIView):
    """用户注册视图"""
    permission_classes = [AllowAny]

    def post(self, request):
        try:
            # 1. 验证注册数据
            registration_serializer = UserRegistrationSerializer(data=request.data)
            if not registration_serializer.is_valid():
                return BaseResponse.error(registration_serializer.errors)

            # 2. 验证验证码
            phone = registration_serializer.validated_data['phone']
            code = request.data.get('verification_code')

            verification_service = VerificationService()
            if not verification_service.verify_code(phone, code):
                return BaseResponse.error('验证码错误或已过期')

            # 3. 创建用户
            user = User.objects.create_user(
                phone=phone,
                password=registration_serializer.validated_data['password']
            )

            # 4. 生成Token
            refresh = RefreshToken.for_user(user)

            return BaseResponse.success({
                'token': str(refresh.access_token),
                'refresh': str(refresh)
            }, '注册成功')

        except Exception as e:
            logger.error(f"注册失败: {str(e)}")
            return BaseResponse.error('注册失败')


@method_decorator(csrf_exempt, name='dispatch')
class SendVerificationCodeView(APIView):
    """发送验证码视图"""
    permission_classes = [AllowAny]

    def post(self, request, *args, **kwargs):
        try:
            # 1. 验证手机号
            serializer = VerificationCodeSerializer(data={'phone': request.data.get('phone')})
            if not serializer.is_valid():
                return Response({
                    "status": "error",
                    "message": serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)

            phone = serializer.validated_data['phone']

            # 2. 检查发送限制
            verification_service = VerificationService()
            if not verification_service.can_send_sms(phone):
                return Response({
                    "status": "error",
                    "message": "发送过于频繁，请稍后再试"
                }, status=status.HTTP_400_BAD_REQUEST)

            # 3. 生成验证码
            code = verification_service.generate_code()

            # 4. 发送短信（使用同步方式）
            sms_client = SMSClient()
            success = sms_client.send_sms_sync(phone, {'code': code})

            if not success:
                return Response({
                    "status": "error",
                    "message": "短信发送失败"
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            # 5. 保存验证码到Redis
            if not verification_service.save_code(phone, code):
                return Response({
                    "status": "error",
                    "message": "验证码保存失败"
                }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            # 6. 测试模式下返回验证码
            response_data = {
                "status": "success",
                "message": "验证码发送成功"
            }
            if settings.SMS_CONFIG.get('TEST_MODE', False):
                response_data['test_code'] = code

            return Response(response_data)

        except Exception as e:
            logger.error(f"发送验证码失败: {str(e)}")
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@method_decorator(csrf_exempt, name='dispatch')
class UserLoginView(APIView):
    """用户登录视图"""
    permission_classes = [AllowAny]

    def post(self, request):
        """处理登录请求"""
        serializer = UserLoginSerializer(data=request.data)
        if serializer.is_valid():
            phone = serializer.validated_data['phone']
            password = serializer.validated_data['password']

            try:
                user = User.objects.get(phone=phone)
                if user.check_password(password):
                    refresh = RefreshToken.for_user(user)
                    return Response({
                        'status': 'success',
                        'data': {
                            'token': str(refresh.access_token),
                            'refresh': str(refresh),
                            'user': {
                                'id': user.id,
                                'phone': user.phone,
                                'username': user.username or '',
                                'is_active': user.is_active
                            }
                        }
                    })
                else:
                    return Response({
                        'status': 'error',
                        'message': '密码错误'
                    }, status=401)
            except User.DoesNotExist:
                return Response({
                    'status': 'error',
                    'message': '用户不存在'
                }, status=401)

        return Response({
            'status': 'error',
            'message': serializer.errors
        }, status=400)


class UserProfileView(APIView):
    """用户信息管理视图"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        try:
            serializer = UserSerializer(request.user, context={'request': request})
            return BaseResponse.success(serializer.data)
        except Exception as e:
            return BaseResponse.error(str(e))

    def put(self, request):
        try:
            user = request.user
            data = request.data.copy()

            if 'phone' in data:
                return BaseResponse.error('手机号不可修改')

            # 处理头像上传
            if 'avatar' in request.FILES:
                avatar_file = request.FILES['avatar']

                # 验证文件类型
                if avatar_file.content_type not in settings.ALLOWED_IMAGE_TYPES:
                    return BaseResponse.error('不支持的文件类型')

                # 验证文件大小
                if avatar_file.size > settings.MAX_UPLOAD_SIZE:
                    return BaseResponse.error('文件大小超过限制')

                # 如果存在旧头像，删除它
                if user.avatar:
                    old_avatar_path = user.avatar.path
                    if os.path.exists(old_avatar_path):
                        os.remove(old_avatar_path)

            serializer = UserSerializer(
                user,
                data=data,
                partial=True,
                context={'request': request}
            )

            if serializer.is_valid():
                serializer.save()
                return BaseResponse.success(serializer.data, '用户信息更新成功')
            return BaseResponse.error(serializer.errors)
        except Exception as e:
            return BaseResponse.error(str(e))


class ChangePasswordView(APIView):
    """修改密码视图"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        serializer = PasswordChangeSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        # 验证旧密码
        if not request.user.check_password(serializer.validated_data['old_password']):
            return Response(
                {'old_password': '旧密码不正确'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 验证新密码
        new_password = serializer.validated_data['new_password']
        new_password_confirm = serializer.validated_data['new_password_confirm']

        if new_password != new_password_confirm:
            return Response(
                {'new_password': '两次输入的新密码不一致'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 修改密码
        request.user.set_password(new_password)
        request.user.save()

        return Response({'message': '密码修改成功'}, status=status.HTTP_200_OK)


class LogoutView(APIView):
    """用户退出登录视图"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            # 获取用户的refresh token
            refresh_token = request.data.get('refresh')
            
            if refresh_token:
                try:
                    # 将refresh token加入黑名单
                    token = RefreshToken(refresh_token)
                    token.blacklist()
                except TokenError:
                    # token已经在黑名单中或无效
                    pass

            # 清除用户相关的缓存
            cache_keys = [
                f'user_profile_{request.user.id}',
                f'user_permissions_{request.user.id}',
                f'user_settings_{request.user.id}'
            ]
            cache.delete_many(cache_keys)
            
            return Response({
                'status': 'success',
                'message': '退出成功',
                'data': {
                    'redirect_url': '/login'
                }
            })
        except Exception as e:
            logger.error(f"Logout error for user {request.user.id}: {str(e)}")
            return Response({
                'status': 'error',
                'message': '退出失败，请稍后重试'
            }, status=status.HTTP_400_BAD_REQUEST)
